<template>
  <div class="app-container" ref="appcontainer">
    <el-row :gutter="10" class="mb8">
      <el-col :span="1.5">
        <el-button type="primary" plain size="mini" @click="handleAdd"
          >新增</el-button
        >
      </el-col>
    </el-row>
    <el-table
      :data="tableData"
      row-key="id"
      style="width: 100%"
      :height="tableHeight"
      default-expand-all
      :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
    >
      <el-table-column label="id" prop="id"> </el-table-column>
      <el-table-column label="分类名称" prop="classifyName"> </el-table-column>
      <el-table-column label="是否启用" prop="state"> </el-table-column>
      <el-table-column label="是否在小程序端使用" prop="showWechat">
      </el-table-column>
      <el-table-column label="排序" prop="orderNum"> </el-table-column>
      <el-table-column fixed="right" label="操作" width="100">
        <template slot-scope="scope">
          <el-button @click="handleEdit(scope.row)" type="text" size="small"
            >编辑</el-button
          >
          <el-button
            @click="handleDelete(scope.row.id)"
            type="text"
            size="small"
            >删除</el-button
          >
        </template>
      </el-table-column>
    </el-table>
    <el-dialog
      title="添加"
      :visible.sync="dialogVisible"
      width="50%"
      @close="handleDialogClose"
    >
      <div class="doalog-col">
        <p class="doalog-col-label">父级分类</p>
        <div class="block">
          <el-cascader
            :options="options"
            :props="{ checkStrictly: true }"
            clearable
            @change="handleCasCHnage"
            v-model="cascader"
          ></el-cascader>
        </div>
      </div>
      <div class="doalog-col">
        <p class="doalog-col-label">分类名称:</p>
        <el-input
          type="text"
          class="doalog-col-input"
          placeholder="请输入分类名称"
          v-model="classifyName"
        ></el-input>
      </div>
      <div class="doalog-col">
        <p class="doalog-col-label">是否启用:</p>
        <el-switch
          v-model="state"
          active-color="#13ce66"
          inactive-color="#ff4949"
        >
        </el-switch>
      </div>
      <div class="doalog-col">
        <p class="doalog-col-label">是否在小程序启用:</p>
        <el-switch
          v-model="showWechat"
          active-color="#13ce66"
          inactive-color="#ff4949"
        >
        </el-switch>
      </div>
      <div class="doalog-col">
        <p class="doalog-col-label">排序:</p>
        <el-input
          type="number"
          class="doalog-col-input"
          v-model="orderNum"
          placeholder="排序"
        ></el-input>
      </div>
      <span slot="footer" class="dialog-footer">
        <el-button @click="handleCancel">取 消</el-button>
        <el-button type="primary" @click="handleClassifyAddOrEdit"
          >确 定</el-button
        >
      </span>
    </el-dialog>
  </div>
</template>

<script>
import {
  getList,
  addClassify,
  editCladdify,
  deleteClassify,
} from "@/api/classify";
export default {
  data() {
    return {
      tableHeight: 0,
      dialogVisible: false,
      tableData: [],
      parentData: [],
      options: [
        {
          label: '顶级分类',
          value: 0
        }
      ],
      classifyName: "",
      state: true,
      showWechat: true,
      orderNum: 0,
      parentId: 0,
      cascader: [],
      isEdit: false,
      currentId: 0,
    };
  },
  methods: {
    calHeight() {
      this.$nextTick(() => {
        const rect = this.$refs.appcontainer.getBoundingClientRect();
        this.tableHeight = rect.height - 80;
      });
    },
    getList() {
      getList().then((res) => {
        // res.rows.sort((a,b) => {
        //   return (a.id - b.id)
        // }).reverse()
        const rows = [...res.rows];
        const len = rows.length - 1;
        for (let i = len; i >= 0; i--) {
          if (rows[i].parentId == 0) {
            this.parentData.push(rows[i]);

            // 处理options
            let copy = { ...rows[i] };
            copy.value = copy.id;
            copy.label = copy.classifyName;
            this.options.push(copy);
            // 处理optionsend
            rows.splice(i, 1);
          }
        }
        //一级分类直接先排序
        this.parentData.sort((a,b) => {
          return (a.orderNum - b.orderNum)
        })
        this.tableData = [...this.parentData];
        //还有长度说明还有子项
        // if (rows.length) {
          
          
        // }
        //处理多级子项
        this.handleMulList(JSON.parse(JSON.stringify(rows)));
        // 子项排序，只排序了二级，需要多级排序，需要递归处理，下次处理时，直接在获取数据的时候根据orderNum排序就行了，不用递归
        this.tableData.forEach(item => {
          if(item.hasOwnProperty('children')) {
            item.children.sort((a,b) => {
              return (a.orderNum - b.orderNum)
            })
          }
        })
        this.handleMulOps(rows)
      });
    },
    handleMulOps(lists) {
      let list = lists || []
      if(list.length === 0) {
        return
      }
      //处理options
      for (let k = list.length - 1; k >= 0; k--) {
        const parentid = list[k].parentId;
        const obj = this.findOpsObj(parentid,this.options);
        if (obj) {
          if (obj.hasOwnProperty("children")) {
            list[k].value = list[k].id
            list[k].label = list[k].classifyName
            obj.children.push(list[k]);
            list.splice(k, 1);
          } else {
            obj.children = [];
            list[k].value = list[k].id
            list[k].label = list[k].classifyName
            obj.children.push(list[k]);
            list.splice(k, 1);
          }
        }
      }
      if (list.length) {
        this.handleMulOps(list);
      }
      //处理options end
    },
    findOpsObj(id,options) {
      let obj = null
      for(let i = 0; i < options.length; i++) {
        if(options[i].value == id) {
          obj = options[i]
          
          break
        } else {
          if(options[i].hasOwnProperty('children')) {
            const result = this.findOpsObj(id,options[i].children)
            if(result) {
              obj = result
            }
            
          }
        }
      }
    return obj
    },
    handleMulList(lists) {
      let list = lists || []
      if(list.length === 0) {
        return
      }
      for (let i = list.length - 1; i >= 0; i--) {
        const parentid = list[i].parentId;
        //根据父级id找到这个对象
        const obj = this.findObj(parentid,this.tableData);
        if (obj) {
          if (obj.hasOwnProperty("children")) {
            obj.children.push(list[i]);
            list.splice(i, 1);
          } else {
            obj.children = [];
            obj.children.push(list[i]);
            list.splice(i, 1);
          }
        }
      }
      //如果数据中还有数据递归处理
      if (list.length) {
        this.handleMulList(list);
      }
    },
    findObj(id,options) {
      let obj = null;
      for (let j = 0; j < options.length; j++) {
        if (options[j].id == id) {
          obj = options[j];
          break;
        } else {
          if (options[j].children) {
            const result = this.findObj(id, options[j].children);
            if(result) {
              obj = result;
              // break;
            }
          }
        }
      }
      return obj;
    },
    handleAdd() {
      this.dialogVisible = true;
    },
    //递归平铺树形结构options
    getObj(tree) {
      const objArr = [];
      tree.forEach((item) => {
        objArr.push(item);
        if (item.children && item.children.length) {
          const arr = this.getObj(item.children);
          objArr = [...objArr, ...arr];
        }
      });
      return objArr;
    },
    //递归获取三级以上分类数组
    getArr(id, resulrtArr) {
      let result = [];
      const obj = resulrtArr.find((item) => {
        return item.id === id;
      });
      if (obj.parentId === 0) {
        result.unshift(obj.id);
      } else {
        result.unshift(obj.id);
        let arr = this.getArr(obj.parentId, resulrtArr);
        result = [...arr, ...result];
      }
      return result;
    },
    handleEdit(row) {
      this.cascader = [];
      this.dialogVisible = true;
      this.isEdit = true;
      this.currentId = row.id;
      if (row.parentId === 0) {
        this.cascader.push(row.id);
      } else {
        this.cascader.unshift(row.id);
        this.cascader.unshift(row.parentId);
        const parentNode = this.options.find((item) => {
          return item.id === row.parentId;
        });
        //顶层找到说明分类是顶级分类
        if (parentNode && parentNode.parentId === 0) {
          // return
        } else {
          const resulrtArr = this.getObj(this.options);
          const result = this.getArr(
            parentNode.parentId,
            Array.from(new Set(resulrtArr))
          );
          this.cascader = [...result, ...this.cascader];
        }
      }
      // this.$nextTick(() => {
      // this.$set('cascader',this.cascader)
      // })
      this.classifyName = row.classifyName;
      this.orderNum = row.orderNum;
      this.showWechat = row.showWechat === "Y" ? true : false;
      this.state = row.state === "Y" ? true : false;
    },
    handleDelete(id) {
      this.$confirm("是否删除分类?", "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          deleteClassify(id).then(() => {
            this.parentData = [];
            this.tableData = [];
            this.getList();
            this.$message({
              type: "success",
              message: "删除成功!",
            });
          });
        })
        .catch(() => {
          this.$message({
            type: "info",
            message: "已取消删除",
          });
        });
    },
    handleCasCHnage(val) {
      this.cascader = val;
      const id = val[val.length - 1];
      this.parentId = id;
    },
    handleDialogClose() {
      this.cascader = [];
      this.parentId = 0;
      this.orderNum = 0;
      this.showWechat = true;
      this.state = true;
      this.classifyName = "";
      this.isEdit = false;
    },
    handleCancel() {
      this.handleDialogClose();
      this.dialogVisible = false;
    },
    handleClassifyAddOrEdit() {
      const data = {
        parentId: this.parentId,
        classifyName: this.classifyName,
        state: this.state ? "Y" : "N",
        showWechat: this.showWechat ? "Y" : "N",
        orderNum: this.orderNum,
      };
      if (this.isEdit) {
        data.id = this.currentId;
        editCladdify(data).then(() => {
          this.dialogVisible = false;
          this.msgSuccess("编辑成功");
          this.parentData = [];
          this.tableData = [];
          this.getList();
        });
      } else {
        addClassify(data).then(() => {
          this.dialogVisible = false;
          this.msgSuccess("新增成功");
          this.parentData = [];
          this.tableData = [];
          this.getList();
        });
      }
    },
  },
  mounted() {
    this.calHeight();
    this.getList();
  },
};
</script>
<style>
.demo-table-expand {
  font-size: 0;
}
.demo-table-expand label {
  width: 90px;
  color: #99a9bf;
}
.demo-table-expand .el-form-item {
  margin-right: 0;
  margin-bottom: 0;
  width: 50%;
}
.doalog-col {
  margin-top: 20px;
  margin-bottom: 20px;
}
.doalog-col-label {
  width: 120px;
  text-align: justify;
  margin: 0;
  margin-right: 10px;
}
.doalog-col {
  display: flex;
  align-items: center;
}
.doalog-col-input {
  width: 180px;
}
</style>